package com.shjn.squirrel.utils;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.shjn.squirrel.model.Constant;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.greenrobot.eventbus.EventBus;

/**
 * CreateTime 2019/8/8 16:11
 * Author LiuShiHua
 * Description：
 */

public class MqttUtil {

    private final String TAG = "------------->mqtt";
    private static MqttUtil mqttUtil;
    private Context context;

    private MqttAndroidClient mqttAndroidClient;
    private MqttConnectOptions mMqttConnectOptions;
    private boolean isConnectSuccess = false;

    //MQTT相关配置
    private  final String CLIENTID = "AndroidUser";
    private  final String HOST = "tcp://205.185.121.29:1883";//服务器地址（协议+地址+端口号）
    private  final String USERNAME = "admin";//用户名
    private  final String PASSWORD = "jiangchuan666";//密码
    private  final String PUBLISH_TOPIC = "topic1";//默认发布主题
    private  final String SUBSCRBEB_TOPIC = "topic2";//默认订阅主题
    private final int CONNECT_TIMEOUT  = 10;//连接超时时间
    private final int KEEPALIVE_INTERVAL =20;//心跳
    private final boolean IS_CLEAN_SESSION =true;//是否清除缓存

    private final int HAND_RECONNECT = 1;//重连hand
    private final int RECONNECT_TIME_CONFIG = 3 * 1000;//重连时间间隔为3秒

    /**
     * QUALITY_OF_SERVICE
     * 至多一次，消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况，环境传感器数据，丢失一次读记录无所谓，因为不久后还会有第二次发送。
     * 至少一次，确保消息到达，但消息重复可能会发生。
     * 只有一次，确保消息到达一次。这一级别可用于如下情况，在计费系统中，消息重复或丢失会导致不正确的结果
     */
    private final int QUALITY_OF_SERVICE = 0;//服务质量,0最多一次，1最少一次，2只一次


    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case HAND_RECONNECT:
                    if (!isConnectSuccess)
                        doClientConnection();//连接失败，重连
                    break;
            }
        }
    };

    //单例模式
    public static MqttUtil getInstance(Context context) {
        if (mqttUtil == null) {
            mqttUtil = new MqttUtil(context);
        }
        return mqttUtil;
    }

    private MqttUtil(Context context) {
        this.context = context;
        initMqtt();
    }

    private void initMqtt() {
        mqttAndroidClient = new MqttAndroidClient(context, HOST, CLIENTID);
        mqttAndroidClient.setCallback(mqttCallback); //设置订阅消息的回调
        mMqttConnectOptions = new MqttConnectOptions();
        mMqttConnectOptions.setCleanSession(IS_CLEAN_SESSION); //设置是否清除缓存
        mMqttConnectOptions.setConnectionTimeout(CONNECT_TIMEOUT); //设置超时时间，单位：秒
        mMqttConnectOptions.setKeepAliveInterval(KEEPALIVE_INTERVAL); //设置心跳包发送间隔，单位：秒
        mMqttConnectOptions.setUserName(USERNAME); //设置用户名
        mMqttConnectOptions.setPassword(PASSWORD.toCharArray()); //设置密码
        doClientConnection();//创建连接
    }

    /**
     * 连接MQTT服务器
     */
    private void doClientConnection() {
        if (!mqttAndroidClient.isConnected()) {
            try {
                mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);
            } catch (MqttException e) {
                Log.d(TAG,"doClientConnection:" + e.getMessage());
                e.printStackTrace();
            }
        }else {
            Log.d(TAG,"已连接");
        }
    }

    //MQTT是否连接成功的监听
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken arg0) {
            Log.i(TAG, "连接成功 ");
            EventBus.getDefault().post("连接成功");
            isConnectSuccess = true;
            try {
                mqttAndroidClient.subscribe(SUBSCRBEB_TOPIC, QUALITY_OF_SERVICE);//订阅主题，参数：主题、服务质量(可追加多个主题)
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable arg1) {
            arg1.printStackTrace();
            Log.i(TAG, "onFailure 连接失败:" + arg1.getMessage());
            EventBus.getDefault().post("连接失败");
            isConnectSuccess = false;
            handler.sendEmptyMessageDelayed(HAND_RECONNECT, RECONNECT_TIME_CONFIG);
        }
    };

    /**
     * 发布消息
     *
     * @param message 消息
     */
    public void publish(String topic, String message, int qos) {
        boolean retained = false;
        try {
            if (mqttAndroidClient != null && mqttAndroidClient.isConnected()) {
                //参数分别为：主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息
                mqttAndroidClient.publish(topic, message.getBytes(), qos, retained);
            } else {
                Log.d(TAG,"mqttAndroidClient is Null");
            }
        } catch (MqttException e) {
            Log.d(TAG,"publish MqttException:" + e.getMessage());
            e.printStackTrace();
        }
    }

    //订阅主题的回调
    private MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) throws Exception {
            Log.i(TAG, "收到消息： " + topic + ":" + new String(message.getPayload()) );
            EventBus.getDefault().post("push--> "+topic+":"+message);
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken arg0) {
            Log.i(TAG, "deliveryComplete");
        }

        @Override
        public void connectionLost(Throwable arg0) {
            Log.i(TAG, "连接断开");
            EventBus.getDefault().post("连接断开");
            isConnectSuccess = false;
            handler.sendEmptyMessageDelayed(HAND_RECONNECT, RECONNECT_TIME_CONFIG);
        }
    };

    //断开链接
    public void disconnect() {
        try {
            if (mqttAndroidClient != null)
                mqttAndroidClient.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}

